﻿using System;
#if !NET40
using System.Threading.Tasks;
#endif
using WeShare.WeiXin.Common;
using WeShare.WeiXin.Common.EnumKey;

namespace WeShare.WeiXin.Common
{
    /// <summary>
    /// 全局接口调用凭据实体类
    /// </summary>
    public class AccessToken
    {
        public int errcode { get; set; }
        public string errmsg { get; set; }
        public string access_token { get; set; }
        public int expires_in { get; set; }
        /// <summary>
        /// 获取access_token，并在获取失败后，返回失败原因。
        /// </summary>
        /// <param name="appId"></param>
        /// <returns></returns>
        public static string GetValue(string appId = "", PlatformType platform = PlatformType.Mp, Action<string> errorAction = null)
        {
            var config = OpenApi.GetConfig(appId, platform);
            if (config == null)
            {
                if (errorAction != null)
                {
                    errorAction("未查找到相关的注册信息，请调用OpenApi.Register(params ApiConfig[]  config)方法进行注册");
                }
            }
            if (OpenApi.IsUseRedisCache)
            {
                //从缓存中获取accessToken
                var value = OpenApi.redis.Get(config.AppId);
                if (!string.IsNullOrEmpty(value))
                {
                    return value;
                }
                var at = GetAccessToken(config.AppId, config.AppSecret);
                if (at.errcode != 0 && errorAction != null)
                {
                    errorAction(at.errmsg);
                    return "";
                }
                OpenApi.redis.Set(config.AppId, at.access_token, at.expires_in / 2);
                return at.access_token;
            }
            else
            {
                var value = CacheService.Get<string>(appId);// CacheHelper.GetValue(appId);
                if (string.IsNullOrEmpty(value))
                {
                    var accesstoken = GetAccessToken(config.AppId, config.AppSecret);
                    if (accesstoken.errcode != 0 && errorAction != null)
                    {
                        errorAction(accesstoken.errmsg);
                        return "";
                    }
                    CacheService.Add(appId, accesstoken.access_token, accesstoken.expires_in / 2);
                    //CacheHelper.Add(appId, accesstoken.access_token, DateTime.Now.AddSeconds(accesstoken.expires_in / 2));
                    value = accesstoken.access_token;
                }
                return value;
            }
        }
        private static AccessToken GetAccessToken(string appId, string appSecret)
        {
            string url = $"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appId}&secret={appSecret}";
            return HttpUtil.GetResult<AccessToken>(url);
        }
#if !NET40
        private static async Task<AccessToken> GetAccessTokenAsync(string appId, string appSecret, Action<string> errorAction = null)
        {
            string url = $"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appId}&secret={appSecret}";
            var at = await HttpUtil.GetResultAsync<AccessToken>(url);
            if (at.errcode > 0)
            {
                if (errorAction != null)
                {
                    errorAction(at.errmsg);
                }
            }
            return at;
        }
        public static async Task<string> GetValueAsync(string appId = "", PlatformType platform = PlatformType.Mp, Action<string> errorAction = null)
        {
            var config = OpenApi.GetConfig(appId, platform);
            if (config == null)
            {
                if (errorAction != null)
                {
                    errorAction("未查找到相关的注册信息，请调用OpenApi.Register(params ApiConfig[]  config)方法进行注册");
                }
            }
            if (OpenApi.IsUseRedisCache)
            {
                //从缓存中获取accessToken
                var value = await OpenApi.redis.GetAsync(config.AppId);
                if (!string.IsNullOrEmpty(value))
                {
                    return value;
                }
                var at = await GetAccessTokenAsync(config.AppId, config.AppSecret);
                if (at.errcode != 0 && errorAction != null)
                {
                    errorAction(at.errmsg);
                    return "";
                }
                OpenApi.redis.SetAsync(config.AppId, at.access_token, at.expires_in / 2);
                return at.access_token;
            }
            else
            {
                var value = CacheService.Get<string>(appId);// CacheHelper.GetValue(appId);
                if (string.IsNullOrEmpty(value))
                {
                    var accesstoken = await GetAccessTokenAsync(config.AppId, config.AppSecret);
                    if (accesstoken.errcode != 0 && errorAction != null)
                    {
                        errorAction(accesstoken.errmsg);
                        return "";
                    }
                    CacheService.Add(appId, accesstoken.access_token, accesstoken.expires_in / 2);
                    //CacheHelper.Add(appId, accesstoken.access_token, DateTime.Now.AddSeconds(accesstoken.expires_in / 2));
                    value = accesstoken.access_token;
                }
                return value;
            }
        }
        public static async Task<string> RefreshAsync(string appId, PlatformType platform = PlatformType.Mp, Action<string> errorAction = null)
        {
            var config = OpenApi.GetConfig(appId, platform);
            if (config == null)
            {
                if (errorAction != null)
                {
                    errorAction("未查找到相关的注册信息，请调用OpenApi.Register(params ApiConfig[]  config)方法进行注册");
                    return "";
                }
            }
            var accesstoken = await GetAccessTokenAsync(config.AppId, config.AppSecret,errorAction);
            if (OpenApi.IsUseRedisCache)
            {

                OpenApi.redis.SetAsync(appId, accesstoken.access_token, accesstoken.expires_in / 2);
            }
            else
            {
                CacheService.Update(appId, accesstoken.access_token, accesstoken.expires_in / 2);
                //CacheHelper.Refresh(appId, accesstoken.access_token, DateTime.Now.AddSeconds(accesstoken.expires_in / 2));
            }
            return accesstoken.access_token;
        }
#endif
        /// <summary>
        /// 强制刷新。用于在未知原因导致的access_ken实效的情况下，强制刷新。由于access_token的接口调用次数限制，请慎用此接口。
        /// </summary>
        /// <param name="appId"></param>
        /// <param name="appSecret"></param>
        /// <param name="errmsg"></param>
        /// <returns></returns>
        public static string Refresh(string appId, PlatformType platform = PlatformType.Mp)
        {
            var config = OpenApi.GetConfig(appId, platform);
            if (config == null)
            {
                throw new Exception("未查找到相关的注册信息，请调用OpenApi.Register(params ApiConfig[]  config)方法进行注册");
            }
            var accesstoken = GetAccessToken(config.AppId, config.AppSecret);
            if (OpenApi.IsUseRedisCache)
            {

                OpenApi.redis.Set(appId, accesstoken.access_token, accesstoken.expires_in / 2);
            }
            else
            {
                CacheService.Update(appId, accesstoken.access_token, accesstoken.expires_in / 2);
                //CacheHelper.Refresh(appId, accesstoken.access_token, DateTime.Now.AddSeconds(accesstoken.expires_in / 2));
            }
            return accesstoken.access_token;
        }
    }
}
